#include<iostream>
#include<cerrno>
#include<cassert>
#include<unistd.h>
#include<string.h>
#include<string>
#include<sys/types.h>

using std::cout;
using std::endl;

int main()
{
    //创建管道所需传参的数组
    int pipefd[2]={0};
    
    //1.创建管道
    int n=pipe(pipefd);
    if(n<0)
    {
        //如果返回值小于0，即-1，还会设置错误码
        //我们再把错误码对应的错误信息，打印一下
        cout<<"pipe error,"<<errno<<":"<<strerror(errno)<<endl;
        return 1;
    }
    cout<<"pipefd[0]:"<<pipefd[0]<<endl;//读端
    cout<<"pipefd[1]:"<<pipefd[1]<<endl;//写端

    //2.创建子进程
    pid_t id = fork();
    //获取错误。意料之外，使用if；意料之中，用assert
    //此处应该使用if，但为了简单一些，使用assert
    assert(id!=-1);

    if(id==0)
    {
        //子进程
        
        //3.关闭不需要的fd
        close(pipefd[0]);//关闭子进程的读端

        //4.开始通信
        const std::string namestr="hello ,我是子进程";
        int cnt=1;//计数器

        char buffer[1024];//write的字符数组

        int Cnt=0;
        while(true)
        {
            // //将内容写入buffer字符串
            // snprintf(buffer,sizeof(buffer)-1,"%s,计数器：%d,我的PID:%d\n",namestr.c_str(),cnt++,getpid());
            // //将内容写入管道
            // write(pipefd[1],buffer,strlen(buffer));
            // sleep(5);

            //子进程的写入
            char x='X';
            write(pipefd[1],&x,1);
            cout<<Cnt++<<endl;

        }



        //关闭子进程的写端，再exit退出
        close(pipefd[1]);
        exit(0);
    }

    //父进程


    //3.关闭不需要的fd
    //让父进程进行读取
    close(pipefd[1]);//关闭父进程的写端


    //4.开始通信
    char buffer[5000];
    while(true)
    {
        sleep(2);
        //读取的大小，至少要留一个位置写入\0
        int n = read(pipefd[0],buffer,5000);
        if(n>0)
        {
            buffer[n]='\0';
            cout<<"我是父进程, child give me a message: "<<buffer<<endl;
        }
        else if(n==0)
        {
            cout<<"我是父进程，子进程退出了"<<endl;
            break;
        }
    }

    
    //关闭父进程的读端，结束进程
    close(pipefd[0]);
    return 0;
}